package com.hmkj.core.api.hrpay;

import com.hmkj.common.utils.OrderNoUtils;
import com.hmkj.core.api.hrpay.utils.ConfigUtils;
import com.hmkj.core.api.hrpay.utils.RSAUtil;
import com.hmkj.core.api.hrpay.utils.SSLClient;
import com.hmkj.core.api.hrpay.utils.SignUtils;
import com.hmkj.core.exception.BussinessException;
import com.xiaoleilu.hutool.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 华融支付接口工具类
 *
 * @author Vector
 * @create 2018-01-15 19:26
 */
@Slf4j
public class HRPayUtils {

    /**
     * 快捷支付第一步-鉴权（发送短信验证码)
     *
     * @param transAmt  订单金额
     * @param notifyUrl 异步回调地址
     * @param name      持卡人姓名
     * @param phone     预留手机号
     * @param idCard    持卡人身份证
     * @param cardNo    银行卡号
     * @param expDate   信用卡有效期YYMM
     * @param cvn2      信用卡安全码
     * @return
     * @throws Exception
     */
    public static Map<String, String> authentication(BigDecimal transAmt, String notifyUrl, String name,
                                                     String phone, String idCard, String cardNo, String expDate, String cvn2) throws Exception {
        DefaultHttpClient httpClient = new SSLClient();
        HttpPost postMethod = new HttpPost(ConfigUtils.getProperty("trans_url"));
        List<BasicNameValuePair> nvps = new ArrayList<BasicNameValuePair>();
        Date transDate = new Date();
        nvps.add(new BasicNameValuePair("requestNo", new SimpleDateFormat("yyyyMMddHHmmssSSS").format(transDate)));
        nvps.add(new BasicNameValuePair("version", "V1.0"));
        nvps.add(new BasicNameValuePair("productId", "0301"));
        nvps.add(new BasicNameValuePair("transId", "13"));
        nvps.add(new BasicNameValuePair("merNo", ConfigUtils.getProperty("merchant_no")));
        nvps.add(new BasicNameValuePair("orderDate", new SimpleDateFormat("yyyyMMdd").format(transDate)));
        nvps.add(new BasicNameValuePair("orderNo", OrderNoUtils.getHRRechargeOrderNo()));
        nvps.add(new BasicNameValuePair("transAmt", String.valueOf(transAmt.multiply(new BigDecimal(100)).intValue())));
        nvps.add(new BasicNameValuePair("notifyUrl", notifyUrl));
        nvps.add(new BasicNameValuePair("cardName", name));
        nvps.add(new BasicNameValuePair("phoneNo", phone));
        nvps.add(new BasicNameValuePair("cardIdcardType", "01"));
        nvps.add(new BasicNameValuePair("cardIdcardNo", idCard));
        nvps.add(new BasicNameValuePair("cardType", "01"));
        nvps.add(new BasicNameValuePair("cardNo", cardNo));
        nvps.add(new BasicNameValuePair("expDate", expDate));
        nvps.add(new BasicNameValuePair("cvn2", cvn2));
        nvps.add(new BasicNameValuePair("commodityName", "用户充值"));
        nvps.add(new BasicNameValuePair("signature", SignUtils.signData(nvps)));

        postMethod.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));
        HttpResponse resp = httpClient.execute(postMethod);
        String str = EntityUtils.toString(resp.getEntity(), "UTF-8");
        int statusCode = resp.getStatusLine().getStatusCode();
        if (200 != statusCode) {
            log.error("返回错误码:" + statusCode);
            throw new BussinessException("返回错误码:" + statusCode);
        }

        if (!SignUtils.verferSignData(str)) {
            throw new BussinessException("验签失败");
        }

        return transResData(str);
    }

    /**
     * 快捷支付第二步-支付
     *
     * @param verifyCode 验证码
     * @param spOrderId  订单号
     * @return
     * @throws Exception
     */
    public static Map<String, String> quickPay(String verifyCode, String spOrderId) throws Exception {
        DefaultHttpClient httpClient = new SSLClient();
        HttpPost postMethod = new HttpPost(ConfigUtils.getProperty("trans_url"));
        List<BasicNameValuePair> nvps = new ArrayList<BasicNameValuePair>();
        nvps.add(new BasicNameValuePair("requestNo", new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date())));
        nvps.add(new BasicNameValuePair("version", "V1.0"));
        nvps.add(new BasicNameValuePair("productId", "0302"));
        nvps.add(new BasicNameValuePair("transId", "15"));
        nvps.add(new BasicNameValuePair("merNo", ConfigUtils.getProperty("merchant_no")));
        nvps.add(new BasicNameValuePair("orderNo", spOrderId));
        nvps.add(new BasicNameValuePair("veriCode", verifyCode));

        nvps.add(new BasicNameValuePair("signature", SignUtils.signData(nvps)));

        postMethod.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));
        HttpResponse resp = httpClient.execute(postMethod);
        String str = EntityUtils.toString(resp.getEntity(), "UTF-8");
        int statusCode = resp.getStatusLine().getStatusCode();
        if (200 != statusCode) {
            log.error("返回错误码:" + statusCode);
            throw new BussinessException("返回错误码:" + statusCode);
        }

        if (!SignUtils.verferSignData(str)) {
            throw new BussinessException("验签失败");
        }

        return transResData(str);
    }

    /**
     * 余额代付
     *
     * @param orderNo   订单号
     * @param notifyUrl 异步回调地址
     * @param transAmt  提现金额
     * @param name      姓名
     * @param cerdId    身份证号
     * @param bankNo    银行卡号
     * @return
     * @throws Exception
     */
    public static Map<String, String> proxyPay(String orderNo, String notifyUrl, BigDecimal transAmt, String name, String cerdId, String bankNo) throws Exception {
        DefaultHttpClient httpClient = new SSLClient();
        HttpPost postMethod = new HttpPost(ConfigUtils.getProperty("trans_url"));
        List<BasicNameValuePair> nvps = new ArrayList<BasicNameValuePair>();
        nvps.add(new BasicNameValuePair("requestNo", new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date())));
        nvps.add(new BasicNameValuePair("version", "V1.0"));
        nvps.add(new BasicNameValuePair("productId", "0201"));// 0201-非垫支,0203-垫支(T0)
        nvps.add(new BasicNameValuePair("transId", "07"));
        nvps.add(new BasicNameValuePair("merNo", ConfigUtils.getProperty("merchant_no")));
        nvps.add(new BasicNameValuePair("orderDate", new SimpleDateFormat("yyyyMMdd").format(new Date())));
        nvps.add(new BasicNameValuePair("orderNo", orderNo));
        nvps.add(new BasicNameValuePair("notifyUrl", notifyUrl));
        nvps.add(new BasicNameValuePair("transAmt", String.valueOf(transAmt.multiply(new BigDecimal(100)).intValue())));
        nvps.add(new BasicNameValuePair("isCompay", "0"));// 0-对私,1-对公
        nvps.add(new BasicNameValuePair("phoneNo", ""));
        nvps.add(new BasicNameValuePair("customerName", name));
        nvps.add(new BasicNameValuePair("cerdType", "01"));
        nvps.add(new BasicNameValuePair("cerdId", cerdId));
        nvps.add(new BasicNameValuePair("accBankNo", ""));
        nvps.add(new BasicNameValuePair("accBankName", ""));
        nvps.add(new BasicNameValuePair("acctNo", bankNo));
        nvps.add(new BasicNameValuePair("note", "用户提现"));
        nvps.add(new BasicNameValuePair("signature", SignUtils.signData(nvps)));

        postMethod.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));
        HttpResponse resp = httpClient.execute(postMethod);
        String str = EntityUtils.toString(resp.getEntity(), "UTF-8");
        int statusCode = resp.getStatusLine().getStatusCode();
        if (200 != statusCode) {
            log.error("返回错误码:" + statusCode);
            throw new BussinessException("返回错误码:" + statusCode);
        }
        if (!SignUtils.verferSignData(str)) {
            throw new BussinessException("验签失败");
        }

        return transResData(str);
    }


    /**
     * 查询订单状态
     *
     * @param productId 快捷：0302   代付：0201
     * @param orderNo   原订单号
     * @return
     * @throws Exception
     */
    public static Map<String, String> queryTransStatus(String productId, String orderNo) throws Exception {
        DefaultHttpClient httpClient = new SSLClient();
        HttpPost postMethod = new HttpPost(ConfigUtils.getProperty("trans_url"));
        List<BasicNameValuePair> nvps = new ArrayList<BasicNameValuePair>();
        nvps.add(new BasicNameValuePair("requestNo", new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date())));
        nvps.add(new BasicNameValuePair("version", "V1.0"));
        nvps.add(new BasicNameValuePair("transId", "04"));
        nvps.add(new BasicNameValuePair("merNo", ConfigUtils.getProperty("merchant_no")));
        nvps.add(new BasicNameValuePair("productId", productId));
        nvps.add(new BasicNameValuePair("orderNo", orderNo));
        nvps.add(new BasicNameValuePair("signature", SignUtils.signData(nvps)));

        postMethod.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));
        HttpResponse resp = httpClient.execute(postMethod);
        String str = EntityUtils.toString(resp.getEntity(), "UTF-8");
        int statusCode = resp.getStatusLine().getStatusCode();
        if (200 != statusCode) {
            log.error("返回错误码:" + statusCode);
            throw new BussinessException("返回错误码:" + statusCode);
        }

        if (!SignUtils.verferSignData(str)) {
            throw new BussinessException("验签失败");
        }

        return transResData(str);
    }


    /**
     * 异步请求数据验签
     *
     * @param retMap
     * @return
     */
    public static boolean verferSignData(Map<String, String> retMap) {

        StringBuffer buf = new StringBuffer();
        String signature = "";
        for (Map.Entry<String, String> entry : retMap.entrySet()) {
            if ("signature".equals(entry.getKey())) {
                signature = entry.getValue();
            } else if (StrUtil.isNotBlank(entry.getValue())) {
                buf.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
            }
        }

        String signatureStr = buf.substring(0, buf.length() - 1);
        System.out.println("验签数据：" + signatureStr);
        System.out.println("数字签名：" + signature);
        return RSAUtil.verifyByKeyPath(signatureStr, signature, ConfigUtils.getProperty("public_key_path"), "UTF-8");
    }

    /**
     * 解析接口返回数据
     *
     * @param str
     * @return
     */
    public static Map<String, String> transResData(String str) {
        Map<String, String> resDataMap = new HashMap<>();
        String data[] = str.split("&");
        StringBuffer buf = new StringBuffer();
        for (int i = 0; i < data.length; i++) {
            String tmp[] = data[i].split("=", 2);
            resDataMap.put(tmp[0], tmp[1]);
        }
        return resDataMap;
    }

}
